<?php

namespace App\Kuafu\WaiMai\Service;

use App\Kuafu\Common\Service\CommonService;
use App\Kuafu\Common\Service\SeparateService;
use App\Kuafu\Mqtt\Enum\MqttCodeEnum;
use App\Kuafu\Mqtt\Service\MqttService;
use App\Kuafu\Order\Enum\CodeEnum;
use App\Kuafu\Order\Model\OrderOperateRecordModel;
use App\Kuafu\Order\Service\OrderInvoiceService;
use App\Kuafu\Pay\Model\Clickhouse\PayStreamCHModel;
use App\Kuafu\Pay\Model\PayStreamModel;
use App\Kuafu\Shop\Enum\ShopCacheEnum;
use App\Kuafu\Shop\Model\Shop;
use App\Kuafu\User\Service\AuthService;
use App\Kuafu\WaiMai\Channel\BaseWaiMai;
use App\Kuafu\WaiMai\Enum\WaiMaiCodeEnum;
use App\Kuafu\WaiMai\Enum\WaiMaiDBEnum;
use App\Kuafu\WaiMai\Exceptions\WaiMaiException;
use App\Kuafu\WaiMai\Jobs\WaiMaiDelayTask;
use App\Kuafu\WaiMai\Model\Clickhouse\WaiMaiOrderCHModel;
use App\Kuafu\WaiMai\Model\WaiMaiOrderIdShopIdMappingModel;
use App\Kuafu\WaiMai\Model\WaiMaiOrderModel;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class WaiMaiOrderService
{
    /**
     * 外卖订单列表
     * @param int $shopId
     * @param string $completeTimeStart
     * @param string $completeTimeEnd
     * @param int|null $serialNum
     * @param int|null $orderStatus
     * @param int|null $sourceType
     * @param string $sortBy
     * @param string $sort
     * @param int $pageSize
     * @param int $pageNum
     * @return array
     */
    public static function orderList(
        int $shopId = 0,
        ?string $completeTimeStart = '',
        ?string $completeTimeEnd = '',
        ?int $serialNum = null,
        ?int $orderStatus = null,
        ?int $sourceType = null,
        string $sortBy = '',
        string $sort = '',
        int $pageSize = 20,
        int $pageNum = 1
    ): array {
        $query = WaiMaiOrderModel::suffix($shopId)
                                 ->where('shopId', $shopId)
                                 ->with('shopRel')
                                 ->when($serialNum > 0, function ($query) use ($serialNum) {
                                     $query->where('serialNum', $serialNum);
                                 })
                                 ->when($orderStatus != WaiMaiDBEnum::ORDER_STATUS_TOTAL,
                                     function ($query) use ($orderStatus) {
                                         $query->where('orderStatus', $orderStatus);
                                     })
                                 ->when($sourceType, function ($query) use ($sourceType) {
                                     $query->where('sourceType', $sourceType);
                                 })
                                 ->when(strlen($completeTimeStart) && strlen($completeTimeEnd),
                                     function ($query) use ($completeTimeStart, $completeTimeEnd) {
                                         $query->whereBetween('createdAt', [
                                             $completeTimeStart,
                                             $completeTimeEnd
                                         ]);
                                     })
                                 ->when(in_array(strtolower($sort), [
                                         'asc',
                                         'desc'
                                     ]) && strlen($sortBy), function ($query) use (
                                     $sort,
                                     $sortBy
                                 ) {
                                     $query->orderBy($sortBy, $sort);
                                 });

        $orderPaginator = (clone $query)
            ->orderByDesc('createdAt')
            ->paginate($pageSize, ['*'], 'pageNum', $pageNum);

        $list = $orderPaginator->map(function ($order) {

            if ($order->isFinishFoods == WaiMaiDBEnum::FINISH_NO && in_array($order->orderStatus, [WaiMaiDBEnum::ORDER_STATUS_2, WaiMaiDBEnum::ORDER_STATUS_3])) {
                $canFinishFoods = true;
            } else {
                $canFinishFoods = false;
            }

            return [
                'shopId'           => $order->shopId,// 店铺id
                'shopName'         => optional($order->shopRel)->name,// 店铺名
                'orderId'          => (string)$order->orderId,// 18位订单号
                'sourceType'       => $order->sourceType,
                'serialNum'        => $order->serialNum,
                'expectTime'       => $order->expectTimeFormat,
                'payPrice'         => (int)$order->payPrice, // 顾客实付
                'expectIncome'     => $order->orderStatus == WaiMaiDBEnum::ORDER_STATUS_7 ? 0 : (int)$order->expectIncome, // 订单实收
                'orderStatus'      => (int)$order->orderStatus, // 订单状态
                'orderStatusText'  => $order->orderStatusText,// 订单状态描述
                'acceptTime'       => $order->acceptTime ? date('Y-m-d H:i:s', $order->acceptTime) : '', // 接单时间
                'completeTime'     => $order->completeTime ? date('Y-m-d H:i:s', $order->completeTime) : '', // 完成时间
                'acceptAdminName'  => $order->acceptAdminName, // 接单员
                'receiverName'     => $order->receiverName, // 收餐人
                'receiverPhone'    => $order->receiverPhone, // 收餐人电话
                'receiverAddress'  => $order->receiverAddress, // 收餐人地址
                'acceptAt'         => $order->acceptTime ? date('Y-m-d H:i:s', $order->acceptTime) : '',
                'createdAt'        => date('Y-m-d H:i:s', $order->createdAt->timestamp),
                'canFinishFoods'   => $canFinishFoods,
                'invoiceStatusOut' => OrderInvoiceService::orderInvoiceStatus($order->invoiceStatus,
                    $order->createdAt->timestamp, $order->invoiceCanCancelCount)
            ];
        });

        $total['count']        = (int)(clone $query)->count();
        $total['payPrice']     = (int)(clone $query)->where('orderStatus', '!=', WaiMaiDBEnum::ORDER_STATUS_7)->sum('payPrice');
        $total['expectIncome'] = (int)(clone $query)->where('orderStatus', '!=', WaiMaiDBEnum::ORDER_STATUS_7)->sum('expectIncome');

        return [
            'count'    => $orderPaginator->total(),
            'list'     => $list,
            'pageNum'  => $pageNum,
            'pageSize' => $pageSize,
            'total'    => $total,
        ];
    }

    /**
     * 订单详情
     * @param int $orderId
     * @param int $flagBackend 默认0 1-后台请求
     * @return array
     * @throws WaiMaiException
     */
    public static function orderDetail(int $orderId, $flagBackend = 0): array
    {
        $shopId = WaiMaiOrderIdShopIdMappingModel::getShopId($orderId);

        $order = WaiMaiOrderModel::suffix($shopId)->find($orderId);
        if ($order) {
            $model = WaiMaiOrderModel::suffix($shopId);
        } else {
            $model = WaiMaiOrderCHModel::query();
        }

        $order  = $model
                                  ->with('shopRel')
                                  ->with('orderDetailsRel')
                                  ->with(['orderOperateRecordRel' => function ($query) {
                                      $query->orderBy('createdAt', 'asc')
                                          ->orderBy('id', 'asc');
                                  }])
                                  ->find($orderId);

        if (!$order) {
            throw new WaiMaiException(WaiMaiCodeEnum::ERR_EMPTY_ORDER_ID);
        }

        // 没接单人，要更新
        if (!$order->acceptAdminName) {
            try {
                $userName = AuthService::getAuthUser()['username'];
            } catch (\Exception $e) {
                $userName = '';
            }
            if ($userName) {
                WaiMaiOrderModel::editAcceptAdminName($orderId, $userName);
            }
        }
        $logs = [];
        if ($flagBackend == 1) {//后台查询log
            $logs = $order->orderOperateRecordRel->map(function (OrderOperateRecordModel $record) {
                    return [
                        'createdAt'      => $record->createdAt ? date('Y-m-d H:i:s', $record->createdAt) : '',
                        'content'        => '',
                        'recordTypeText' => $record->recordTypeText,
                        'username'       => $record->username,
                    ];
                });
        }

        $productsTotal = [];
        $products = optional($order->orderDetailsRel)->map(function ($item) use ($order) {
            $type        = $item->type;
            $packageList = [];
            $commodities = json_decode($item->commodities ?? "", true);
            if ($commodities) {
                $type = 1;
                foreach ($commodities as $k => $v) {
                    $packageList[] = [// 复用堂食订单详细返回子菜数据
                        "index"              => $k,
                        "totalDiscountPrice" => 0,
                        "productId"          => 0,
                        "productName"        => $v['name'] ?? '',
                        "unit"               => $v['unit'] ?? '',
                        "num"                => $v['count'] ?? '',
                        "originalPrice"      => $v['price'] ?? '',
                        "discountPrice"      => 0,
                        "payPrice"           => 0,
                        "type"               => 0,
                        "packageDetailId"    => "",
                        "id"                 => "",
                        "detailId"           => "",
                        "packageUnitNum"     => 0
                    ];
                }
            }
            $res = CommonService::getIsPrintLabelByName($item->productName, $order->sourceType);//匹配打印配置

            return [
                'name'     => $item->productName,
                'property' => $item->productProperty,
                'num'      => $item->num,
                'price'    => $item->originalPrice,
                'pocketId' => $item->pocketId,
                'refundNum' => $item->partRefundNum,
                'type'               => $type,
                'unit'               => $item->unit,
                'originalPrice'      => $item->originalPrice,
                'payPrice'           => $item->payPrice,
                'totalDiscountPrice' => $item->discountPrice,
                'isPrintLabel'       => $res['isPrintLabel'],// 默认0-不打印 1-打印
                'printLabelType'     => $res['printLabelType'],// 默认0-不打印 1-饮品打印 2-非饮品打印
                'packageList'        => $packageList,
            ];
        })->sortBy('pocketId')->each(function ($item) use (&$productsTotal) {
            if ($item['refundNum'] <= 0) {
                $item['isRefund'] = false;
                unset($item['refundNum']);
                $productsTotal[] = $item;
                return;
            }

            // 拆

            // 正常部分
            $common = $item;
            $common['num'] -= $common['refundNum'];
            if ($common['num'] > 0) {
                $common['isRefund'] = false;
                unset($common['refundNum']);
                $productsTotal[] = $common;
            }

            // 退款部分
            $refund = $item;
            $refund['num'] = $item['refundNum'];
            $refund['isRefund'] = true;
            unset($refund['refundNum']);
            $productsTotal[] = $refund;
        });

        $logs = [];
        if ($flagBackend == 1) {//后台查询log
            $logs = $order->orderOperateRecordRel->map(function (OrderOperateRecordModel $record) {
                    return [
                        'createdAt'      => $record->createdAt ? date('Y-m-d H:i:s', $record->createdAt) : '',
                        'content'        => '',
                        'recordTypeText' => $record->recordTypeText,
                        'username'       => $record->username,
                    ];
                });
        }
        return [

            // 基础信息
            'base'         => [
                'serialNum'        => $serialNum = $order->serialNum,
                'title'            => $order->sourceTypeText . '#' . $serialNum,
                'expectTime'       => $order->expectTimeFormat,
                'createdAt'        => date('Y-m-d H:i:s', is_int($order->createdAt) ? $order->createdAt : $order->createdAt->timestamp),
                'acceptAt'         => $order->acceptTime ? date('Y-m-d H:i:s', $order->acceptTime) : '',
                'completeTime'     => $order->completeTime ? date('Y-m-d H:i:s', $order->completeTime) : '',
                'orderId'          => (string)$orderId,
                'shopCode'         => optional($order->shopRel)->kfShopCode,
                'shopName'         => optional($order->shopRel)->name,
                'orderStatus'      => $order->orderStatus,
                'orderStatusText'  => $order->orderStatusText,
                'sourceType'       => $order->sourceType,
                'sourceTypeText'   => $order->sourceTypeText,
                'acceptAdminName'  => $order->acceptAdminName, // 接单人
                'refundStatus'     => $order->refundStatus, // 退款状态，自己算的
                'refundStatusText' => WaiMaiDBEnum::REFUND_STATUS_TEXT[$order->refundStatus], // 退款状态文案
                'refundPrice'      => $order->refundPrice, // 退款金额
                'canRefundConfirm' => $order->orderStatus == WaiMaiDBEnum::ORDER_STATUS_6, // 是否能确认退款
                'refundReason'     => $order->refundReason,
                'refundPicArr'     => $order->refundPicArr,
            ],

            // 收件人
            'receiverInfo' => [
                'address'      => $order->receiverAddress,
                'name'         => $order->receiverName,
                'phone'        => $order->phoneCombine,
                'privacyPhone' => $order->receiverPrivacyPhoneArr[0] ?? '', // 隐私号
                'bakPhone'     => $order->receiverPrivacyPhoneArr[1] ?? '' //  备用隐私号
            ],

            // 配送员
            'senderInfo' => [
                'name'            => $order->senderName,
                'phone'           => $order->senderPhone,
                'receiverName'    => $order->receiverName,
                'receiverPhone'   => $order->receiverPhone,
                'receiverAddress' => $order->receiverAddress,
            ],

            // 菜品
            'products' => $productsTotal,

            // 菜品统计
            'productsAgg'  => [
                'count' => $products->count(),
                'sum'   => $products->sum('price'),
            ],

            // 价格
            'price'        => [
                'originalPrice'      => $originalPrice = $order->originalPrice - $order->originalShippingPrice,
                // 营业额
                'productPrice'       => $productPrice = $originalPrice - $order->packingPrice,
                // 菜品总价
                'shippingPrice'      => $order->shippingPrice,
                // 配送费
                'packingPrice'       => $order->packingPrice,
                // 餐盒费
                'totalPrice'         => $totalPrice = $productPrice + $order->shippingPrice + $order->packingPrice,
                // 总价=菜品总价+优惠配送费+餐盒费
                'fullReductionPrice' => $order->fullReductionPrice,
                // 满减
                'redPrice'           => $order->redPrice,
                // 优惠总金额
                'payPrice'           => $order->payPrice,
                // 实付
                'platformPrice'      => $order->platformPrice,
                // 平台服务费
                'refundPrice'        => $order->refundPrice,
                // 退款金额
                'expectIncome'       => $order->expectIncome,
                // 订单实收
                'shouldPrice'        => $order->payPrice,
                // 应付金额

                // 其他支出 = 原价 + 餐盒费 - 预计收入 - 服务费 - 部分退款
                'otherPrice'         => $order->otherPrice,
                'redList'            => collect((array)json_decode($order->redLists, true))->map(function ($item) {
                    if (isset($item['p'])) {
                        $item['p'] = abs($item['p']) * -1;
                    }

                    return $item;
                })->values(),
                'merchantDiscount'   => $totalPrice - $order->payPrice,
                // 商家app用，其他支出 （菜品总价+优惠配送费+餐盒费-实付）
            ],

            // 备注
            'remark'       => $order->remark,
            'logs'         => $logs,
            // 开票信息
            'invoiceInfo'  => [
                'invoiceStatusOut'      => OrderInvoiceService::orderInvoiceStatus($order->invoiceStatus,
                    is_int($order->createdAt) ? $order->createdAt : $order->createdAt->timestamp, $order->invoiceCanCancelCount),
                'invoiceUrl'            => OrderInvoiceService::genOrderInvoiceUrl($order->orderId,
                    $order->invoiceStatus,
                    $order->shopId, 2),
                'invoiceCanCancelCount' => $order->invoiceCanCancelCount
            ],
            // 安心卡
            'secureCard' => null,

            // 门店联系手机号
            'shopPhones' => Cache::remember("waiMaiShopPhones:{$order->sourceType}:{$order->shopId}", 3600 * 6,
                function () use ($order) {
                    return BaseWaiMai::getIns($order->sourceType, $order->shopId)->getShop()['data']['phones'] ?? [];
                }),

            // 外卖平台的顾客预留发票信息
            'userTaxInfo' => $order->taxInfo,
        ];
    }

    /**
     * 商家出餐
     * @param int $orderId
     * @param int $shopId
     * @return bool
     * @throws WaiMaiException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public static function sFinishFoods(int $orderId, int $shopId): bool
    {
        $order = WaiMaiOrderModel::suffix($shopId)->find($orderId);
        if (!$order || $order->shopId != $shopId) {
            throw new WaiMaiException(WaiMaiCodeEnum::ERR_EMPTY_ORDER_ID);
        }

        if ($order->orderStatus != WaiMaiDBEnum::ORDER_STATUS_2 && $order->orderStatus != WaiMaiDBEnum::ORDER_STATUS_3) {
            throw new WaiMaiException(WaiMaiCodeEnum::ERR_STATUS_FINISH_FOODS);
        }

        if ($order->isFinishFoods == WaiMaiDBEnum::FINISH_OK) {
            throw new WaiMaiException(WaiMaiCodeEnum::ERR_DO_FINISH_FOODS, "该订单已出餐，请勿重复出餐");
        }

        $s = BaseWaiMai::getIns($order->sourceType, $shopId)->finishFoods($orderId);
        if (!$s['status']) {

            $msg = $s['msg'] ?? '';
            Log::channel('waiMai')->info("sFinishFoodsLog shopId:{$shopId} orderId:{$order->orderId} error ...{$msg}");

            if (time() - $order->acceptTime <= 180) {
                Log::channel('waiMai')->info("sFinishFoodsLog shopId:{$shopId} orderId:{$order->orderId} less time msg:{$msg}");
            }

            // 兼容已出餐 - 幂等
            $orderStatus = BaseWaiMai::getIns($order->sourceType, $shopId)
                                     ->getOrderDetail($orderId)['data']['orderStatus'] ?? 0;

            // 是否已出餐
            $isFinishFoods = BaseWaiMai::getIns($order->sourceType, $shopId)->isFinishFoods($orderId)['data']['finish'] ?? 0;

            // 考虑到别的状态，还会需要更新别的字段，仅更新已出餐的情况
            if ($orderStatus == WaiMaiDBEnum::ORDER_STATUS_3) {
                WaiMaiOrderModel::finishFoods($orderId, $shopId, $isFinishFoods);

                return false;
            }

            throw new WaiMaiException(WaiMaiCodeEnum::ERR_DO_FINISH_FOODS, $s['msg']);
        }

        WaiMaiOrderModel::finishFoods($orderId, $shopId, WaiMaiDBEnum::FINISH_OK);

        Log::channel('waiMai')->info("sFinishFoodsLog shopId:{$shopId} orderId:{$order->orderId} success ...");

        return true;
    }

    /**
     * 商家回复订单退款
     * @param int $orderId
     * @param int $shopId
     * @param string $reason
     * @param bool $agree
     * @return array
     * @throws WaiMaiException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public static function sConfirmRefund(int $orderId, int $shopId, string $reason, bool $agree): bool
    {
        $order = WaiMaiOrderModel::suffix($shopId)->find($orderId);
        if (!$order || $order->shopId != $shopId) {
            throw new WaiMaiException(WaiMaiCodeEnum::ERR_EMPTY_ORDER_ID);
        }

        if ($order->orderStatus != WaiMaiDBEnum::ORDER_STATUS_6) {
            throw new WaiMaiException(WaiMaiCodeEnum::ERR_STATUS_CONFIRM_REFUND);
        }

        $obj = BaseWaiMai::getIns($order->sourceType, $shopId);

        if ($agree) {
            $s = $obj->refundAgree($orderId);
        } else {
            $s = $obj->refundReject($orderId, $reason);
        }

        Log::info('sConfirmRefund Res:', $s);

        if (!$s['status']) {
            throw new WaiMaiException(WaiMaiCodeEnum::ERR_DO_CONFIRM_REFUND, $s['msg']);
        }

        return true;
    }

    /**
     * 预约单提醒
     * @param int $orderId
     * @throws WaiMaiException
     */
    public static function reserveNotice(int $orderId, int $reservedType, int $shopId): bool
    {
        $order = WaiMaiOrderModel::suffix($shopId)->find($orderId);
        if (!$order) {
            throw new WaiMaiException(WaiMaiCodeEnum::ERR_EMPTY_ORDER_ID);
        }

        if ($order->orderStatus >= WaiMaiDBEnum::ORDER_STATUS_3) {
            throw new WaiMaiException(WaiMaiCodeEnum::ERR_STATUS_FINISH_FOODS);
        }

        (new MqttService(0, $order->shopId))->takeOutOrder($orderId, $order->sourceType,
            MqttCodeEnum::TAKE_OUT_OPERATE_TYPE_7, ['reservedType' => $reservedType]);

        return true;
    }

    /**
     * 预约单塞入Queue
     * @param int $orderId
     * @param int $expectFast
     * @param int $expectTime
     */
    public static function reserveNoticeToQueue(int $orderId, int $expectFast, int $expectTime): void
    {
        if ($expectFast == 0) {

            foreach (WaiMaiDelayTask::TASK_DELAY_TIME[WaiMaiDelayTask::TASK_TYPE_2] as $reservedType => $seconds) {
                $delaySeconds = $expectTime - $seconds - time();
                if ($delaySeconds > 0) {
                    WaiMaiDelayTask::dispatch(WaiMaiDelayTask::TASK_TYPE_2, $orderId, ['reservedType' => $reservedType])
                                   ->onQueue(WaiMaiDelayTask::QUEUE_NAME)
                                   ->delay($delaySeconds);

                    Log::info('Reserved Order Delay', ['orderId' => $orderId, 'delay' => $delaySeconds]);
                }
            }
        }
    }

    /**
     * 自动出餐
     * @param int $orderId
     * @param int $expectTime
     * @param int $expectFast
     */
    public static function finishFoodsToQueue(int $orderId, int $expectFast, int $expectTime)
    {
        if ($expectFast == 1) {

            // 即时单 - 延迟12分钟自动出餐
            $delaySeconds = WaiMaiDelayTask::TASK_DELAY_TIME[WaiMaiDelayTask::TASK_TYPE_1][$expectFast];
        } else {

            // 预约单 - 预约时间-30分钟
            $delaySeconds = $expectTime - time() - WaiMaiDelayTask::TASK_DELAY_TIME[WaiMaiDelayTask::TASK_TYPE_1][0];
        }

        WaiMaiDelayTask::dispatch(WaiMaiDelayTask::TASK_TYPE_1, $orderId)
                       ->onQueue(WaiMaiDelayTask::QUEUE_NAME)
                       ->delay($delaySeconds);
    }

    /**
     * 直营店的白名单列表
     * @return array
     */
    public static function directWhiteShopIds(): array
    {
        return Cache::remember(ShopCacheEnum::getDirectWhiteShopIds(), 600, function () {
            $directShopIds = Shop::query()->where('type', \App\Kuafu\Shop\Enum\CodeEnum::TYPE_DIRECT)->pluck('id')->toArray();
            $directShopIds[] = 12018; // 罗老师的店
            return $directShopIds;
        });
    }

    /**
     * 判断是否为白名单店铺
     * @param int $shopId
     * @return bool
     */
    public static function checkWhiteShopId(int $shopId): bool
    {
        return in_array($shopId, self::directWhiteShopIds());
    }


    /**
     * 后台-外卖订单列表
     * @param int $shopId
     * @param string|null $completeTimeStart
     * @param string|null $completeTimeEnd
     * @param int|null $orderStatus
     * @param int|null $sourceType
     * @param int $pageSize
     * @param int $pageNum
     * @param string|null $orderId
     * @param bool $export
     * @return array
     */
    public static function waiMaiOrderList(
        int $shopId = 0,
        ?string $completeTimeStart = '',
        ?string $completeTimeEnd = '',
        ?int $orderStatus = 0,
        ?int $sourceType = 0,
        int $pageSize = 20,
        int $pageNum = 1,
        ?string $orderId = '',
        $export = false,
        $serialNum = 0
    ): array {

        $engine = (new SeparateService(strtotime($completeTimeStart), strtotime($completeTimeEnd) + 86399))->check();
        if ($engine == SeparateService::DB) {
            $model = WaiMaiOrderModel::suffix($shopId);
        } else {
            $model = WaiMaiOrderCHModel::query();
        }

        $query = $model
            ->where('shopId', $shopId)
            ->with('shopRel')
            ->when($serialNum > 0,
                function ($query) use ($serialNum) {
                    $query->where('serialNum', $serialNum);
                })
            ->when($orderStatus != WaiMaiDBEnum::ORDER_STATUS_TOTAL,
                function ($query) use ($orderStatus) {
                    $query->where('orderStatus', $orderStatus);
                })
            ->when($sourceType, function ($query) use ($sourceType) {
                $query->where('sourceType', $sourceType);
            })
            ->when($orderId, function ($query) use ($orderId) {
                $query->where('orderId', $orderId);
            })
            ->when(strlen($completeTimeStart) && strlen($completeTimeEnd),
                function ($query) use ($completeTimeStart, $completeTimeEnd) {
                    $query->whereBetween('completeTime', [strtotime($completeTimeStart), strtotime($completeTimeEnd) + 86400]);
                });

        $totalCount = $query->count();

        $orderPaginator = (clone $query)
            ->orderBy('createdAt', 'desc')
            ->when($export,
                function ($query) {
                    return $query->get();
                },
                function ($query) use ($pageSize, $pageNum) {
                    return $query->simplePaginate($pageSize, ['*'], 'page', $pageNum);
                });

        $list = $orderPaginator->map(function ($order) {
            return [
                'shopId'           => $order->shopId, // 店铺id
                'shopCode'         => optional($order->shopRel)->shopCode, // 店铺编号
                'shopName'         => optional($order->shopRel)->name, // 店铺名
                'orderId'          => (string)$order->orderId, // 18位订单号
                'serialNum'        => $order->serialNum,
                'sourceType'       => $order->sourceType,
                'sourceTypeText'   => $order->sourceTypeText,
                'payPrice'         => (int)$order->payPrice, // 顾客实付
                'expectIncome'     => $order->orderStatus == WaiMaiDBEnum::ORDER_STATUS_7 ? 0 : (int)$order->expectIncome, // 订单实收
                'orderStatus'      => (int)$order->orderStatus, // 订单状态
                'orderStatusText'  => $order->orderStatusText, // 订单状态描述
                'acceptTime'       => $order->acceptTime ? date('Y-m-d H:i:s', $order->acceptTime) : '', // 接单时间
                'completeTime'     => $order->completeTime ? date('Y-m-d H:i:s', $order->completeTime) : '', // 完成时间
                'acceptAt'         => $order->acceptTime ? date('Y-m-d H:i:s', $order->acceptTime) : '',
                'createdAt'        => date('Y-m-d H:i:s', is_int($order->createdAt) ? $order->createdAt : $order->createdAt->timestamp),
                'redPrice'         => $order->redPrice, // 所有优惠金额
                'refundPrice'      => $order->refundPrice, // 退款金额
                'divisionBillId'   => (int)$order->divisionBillId, // 分佣的账单 ID
                'brokerage'        => $order->brokerage, // 佣金
                'refundStatus'     => $order->refundStatus, // 退款状态，自己算的
                'refundStatusText' => WaiMaiDBEnum::REFUND_STATUS_TEXT[$order->refundStatus], // 退款状态文案
                'originalPrice'    => (int)$order->originalPrice, //营业额
                'settlePrice'      => (int)($order->expectIncome - $order->brokerage), //结算金额 订单实收-佣金
                'totalPrice'       => ($order->originalPrice - $order->originalShippingPrice - $order->packingPrice)
                    + $order->shippingPrice + $order->packingPrice,//总价=菜品总价+优惠配送费+餐盒费
            ];
        });

        $total['count']         = (int)(clone $query)->count();
        $total['originalPrice'] = (int)(clone $query)->where('orderStatus', '!=', WaiMaiDBEnum::ORDER_STATUS_7)->sum('originalPrice');//营业额
        $total['redPrice']      = (int)(clone $query)->where('orderStatus', '!=', WaiMaiDBEnum::ORDER_STATUS_7)->sum('redPrice');//所有优惠金额
        $total['expectIncome']  = (int)(clone $query)->where('orderStatus', '!=', WaiMaiDBEnum::ORDER_STATUS_7)->sum('expectIncome');//订单实收
        $total['payPrice']      = (int)(clone $query)->where('orderStatus', '!=', WaiMaiDBEnum::ORDER_STATUS_7)->sum('payPrice');//顾客实付
        $total['refundPrice']   = (int)(clone $query)->where('orderStatus', '!=', WaiMaiDBEnum::ORDER_STATUS_7)->sum('refundPrice');//退款金额
        $total['brokerage']     = (int)(clone $query)->where('orderStatus', '!=', WaiMaiDBEnum::ORDER_STATUS_7)->sum('brokerage');//佣金
        $total['settlePrice']   = (int)($total['expectIncome']-$total['brokerage']);//结算金额 订单实收-佣金

        $originalShippingPrice = (int)(clone $query)->where('orderStatus', '!=', WaiMaiDBEnum::ORDER_STATUS_7)->sum('originalShippingPrice');//原配送费
        $packingPrice          = (int)(clone $query)->where('orderStatus', '!=', WaiMaiDBEnum::ORDER_STATUS_7)->sum('packingPrice');//包装费
        $shippingPrice         = (int)(clone $query)->where('orderStatus', '!=', WaiMaiDBEnum::ORDER_STATUS_7)->sum('shippingPrice');//实付的配送费
        $total['totalPrice']   = ($total['originalPrice'] - $originalShippingPrice - $packingPrice) + $shippingPrice + $packingPrice;//订单原价-营业额 总价=菜品总价+优惠配送费+餐盒费
        if ($export) {
            self::exportWaiMaiOrder($list, $total);
        }
        return [
            'list'     => $list,
            'total'    => $total,
            'pageNum'  => $orderPaginator->currentPage(),
            'pageSize' => $orderPaginator->perPage(),
            'count'    => $totalCount,
        ];
    }


    /**
     * 外卖订单列表-导出
     * @param $list
     * @param array $total
     */
    public static function exportWaiMaiOrder($list, $total = [])
    {
        ini_set('max_execution_time', 100000);
        header("Content-Disposition: attachment; filename=" . urlencode('外卖订单列表') . date('Y-m-d') . '.csv');

        // UTF8的BOM头
        $fd = fopen('php://output', 'w+');
        fwrite($fd, "\xEF\xBB\xBF");

        // 表头
        fputcsv(
            $fd, [
                '门店编号',
                '门店名称',
                '订单号',
                '平台',
                '流水号',
                '订单原价',
                '订单优惠',
                '订单实收',
                '顾客实付',
                '结算金额',
                '平台佣金',
                '订单状态',
                '退款状态',
                '退款金额',
                '完成时间',
            ]
        );

        $list->each(
            function ($item) use (&$fd) {
                fputcsv(
                    $fd, [
                        $item['shopCode'],
                        $item['shopName'],
                        "'" . $item['orderId'],
                        $item['sourceTypeText'],
                        $item['serialNum'],
                        bcdiv100($item['totalPrice']),
                        bcdiv100($item['redPrice']),
                        bcdiv100($item['expectIncome']),
                        bcdiv100($item['payPrice']),
                        bcdiv100($item['settlePrice']),
                        bcdiv100($item['brokerage']),
                        $item['orderStatusText'],
                        $item['refundStatusText'],
                        bcdiv100($item['refundPrice']),
                        $item['completeTime'],
                    ]
                );
                ob_flush();
                flush();
            }
        );

        fputcsv($fd, []);

        if (is_resource($fd)) {
            fclose($fd);
        }
        die;
    }

}
